#pragma once

#ifndef _CR_HTTP_MULTIPART_H
#define _CR_HTTP_MULTIPART_H

NS_CR_BEGIN

namespace http
{
	struct File 
	{
		template <typename StringType>
		explicit File(StringType&& filepath)
			: filepath{ _STD_FWD(filepath) } 
		{}
		
		string filepath;
	};

	struct Buffer 
	{
		typedef const unsigned char* data_t;

		template <typename Iterator, typename StringType>
		explicit Buffer(Iterator begin, Iterator end, StringType&& filename)
			: data{ reinterpret_cast<data_t>(&(*begin)) }
			, datalen{ static_cast<unsigned long>(_STD distance(begin, end)) }
			, filename{ _STD_FWD(filename) } 
		{
			is_random_access_iterator(begin, end);
			static_assert(sizeof(*begin) == 1, "only byte buffers can be used");
		}

		template <typename Iterator>
		typename _STD enable_if<_STD is_same<typename _STD iterator_traits<Iterator>::iterator_category,
			_STD random_access_iterator_tag>::value>::type
			is_random_access_iterator(Iterator /* begin */, Iterator /* end */) 
		{}

		data_t data;
		unsigned long datalen;
		string filename;
	};
	
	struct Part 
	{
		Part(const _STD string& name, const string& value, const _STD string& content_type = {})
			: name{ name }
			, value{ value }
			, content_type{ content_type }
			, is_file{ false }
			, is_buffer{ false } 
		{}
		Part(const _STD string& name, const  int32_t& value, const _STD string& content_type = {})
			: name{ name }
			, value{ _STD to_string(value) }
			, content_type{ content_type }
			, is_file{ false }
			, is_buffer{ false } 
		{}
		Part(const _STD string& name, const File& file, const _STD string& content_type = {})
			: name{ name }
			, value{ file.filepath }
			, content_type{ content_type }
			, is_file{ true }
			, is_buffer{ false } 
		{}
		Part(const _STD string& name, const Buffer& buffer, const _STD string& content_type = {})
			: name{ name }
			, value{ buffer.filename }
			, content_type{ content_type }
			, data{ buffer.data }
			, datalen{ buffer.datalen }
			, is_file{ false }
			, is_buffer{ true } 
		{}

		string name;
		string value;
		string content_type;
		Buffer::data_t data;
		unsigned long datalen;
		bool is_file;
		bool is_buffer;
	};

	class Multipart
	{
	public:
		Multipart(const _STD initializer_list<Part>& parts) 
			: parts( parts )
		{}

		_STD vector<Part> parts;
	};
}

NS_CR_END

#endif // !_CR_HTTP_MULTIPART_H


